From: Giovanni Campagna Date: Wed, 14 Aug 2013 08:34:58 +0000 (+0200) Subject: ShellRecorder: update to use MetaCursorTracker X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~1013^2^2~3693 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=d52c95a15f5e;p=gnome-shell.git ShellRecorder: update to use MetaCursorTracker Replace more direct XFixes usage with a the appropriate abstraction API from mutter, which is guaranteed to work in wayland too. It doesn't yet replace pointer position tracking, although probably it should. Also, because now we're using Mutter API, we lose the standalone test case. https://bugzilla.gnome.org/show_bug.cgi?id=705911 --- diff --git a/js/ui/screencast.js b/js/ui/screencast.js index 61dc692ef..5b3c41922 100644 --- a/js/ui/screencast.js +++ b/js/ui/screencast.js @@ -52,7 +52,8 @@ const ScreencastService = new Lang.Class({ _ensureRecorderForSender: function(sender) { let recorder = this._recorders.get(sender); if (!recorder) { - recorder = new Shell.Recorder({ stage: global.stage }); + recorder = new Shell.Recorder({ stage: global.stage, + screen: global.screen }); recorder._watchNameId = Gio.bus_watch_name(Gio.BusType.SESSION, sender, 0, null, Lang.bind(this, this._onNameVanished)); diff --git a/src/Makefile.am b/src/Makefile.am index 74c6c299b..a5e74b986 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -226,14 +226,6 @@ shell_recorder_private_sources = \ shell_private_sources += $(shell_recorder_private_sources) -noinst_PROGRAMS += test-recorder - -test_recorder_CPPFLAGS = $(TEST_SHELL_RECORDER_CFLAGS) -test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS) - -test_recorder_SOURCES = \ - $(shell_recorder_sources) $(shell_recorder_private_sources) \ - test-recorder.c endif BUILD_RECORDER ######################################## diff --git a/src/shell-recorder.c b/src/shell-recorder.c index 6b2bdfa64..23f2c072c 100644 --- a/src/shell-recorder.c +++ b/src/shell-recorder.c @@ -14,11 +14,14 @@ #include #include +#include +#include +#include + #include "shell-recorder-src.h" #include "shell-recorder.h" #include -#include #include #include @@ -64,14 +67,13 @@ struct _ShellRecorder { int pointer_x; int pointer_y; - gboolean have_xfixes; - int xfixes_event_base; - int xinput_opcode; GSettings *a11y_settings; gboolean draw_cursor; + MetaCursorTracker *cursor_tracker; cairo_surface_t *cursor_image; + guint8 *cursor_memory; int cursor_hot_x; int cursor_hot_y; @@ -121,6 +123,7 @@ static void recorder_pipeline_closed (RecorderPipeline *pipeline); enum { PROP_0, + PROP_SCREEN, PROP_STAGE, PROP_FRAMERATE, PROP_PIPELINE, @@ -242,6 +245,8 @@ shell_recorder_finalize (GObject *object) if (recorder->cursor_image) cairo_surface_destroy (recorder->cursor_image); + if (recorder->cursor_memory) + g_free (recorder->cursor_memory); recorder_set_stage (recorder, NULL); recorder_set_pipeline (recorder, NULL); @@ -322,38 +327,24 @@ recorder_remove_redraw_timeout (ShellRecorder *recorder) static void recorder_fetch_cursor_image (ShellRecorder *recorder) { - XFixesCursorImage *cursor_image; - guchar *data; + CoglTexture *texture; + int width, height; int stride; - int i, j; - - if (!recorder->have_xfixes) - return; - - cursor_image = XFixesGetCursorImage (clutter_x11_get_default_display ()); - if (!cursor_image) - return; - - recorder->cursor_hot_x = cursor_image->xhot; - recorder->cursor_hot_y = cursor_image->yhot; - - recorder->cursor_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - cursor_image->width, - cursor_image->height); - - /* The pixel data (in typical Xlib breakage) is longs even on - * 64-bit platforms, so we have to data-convert there. For simplicity, - * just do it always - */ - data = cairo_image_surface_get_data (recorder->cursor_image); - stride = cairo_image_surface_get_stride (recorder->cursor_image); - for (i = 0; i < cursor_image->height; i++) - for (j = 0; j < cursor_image->width; j++) - *(guint32 *)(data + i * stride + 4 * j) = cursor_image->pixels[i * cursor_image->width + j]; - - cairo_surface_mark_dirty (recorder->cursor_image); + guint8 *data; - XFree (cursor_image); + texture = meta_cursor_tracker_get_sprite (recorder->cursor_tracker); + width = cogl_texture_get_width (texture); + height = cogl_texture_get_height (texture); + stride = 4 * width; + data = g_new (guint8, stride * height); + cogl_texture_get_data (texture, CLUTTER_CAIRO_FORMAT_ARGB32, stride, data); + + /* FIXME: cairo-gl? */ + recorder->cursor_image = cairo_image_surface_create_for_data (data, + CAIRO_FORMAT_ARGB32, + width, height, + stride); + recorder->cursor_memory = data; } /* Overlay the cursor image on the frame. We draw the cursor image @@ -546,6 +537,24 @@ recorder_queue_redraw (ShellRecorder *recorder) recorder_idle_redraw, recorder, NULL); } +static void +on_cursor_changed (MetaCursorTracker *tracker, + ShellRecorder *recorder) +{ + if (recorder->cursor_image) + { + cairo_surface_destroy (recorder->cursor_image); + recorder->cursor_image = NULL; + } + if (recorder->cursor_memory) + { + g_free (recorder->cursor_memory); + recorder->cursor_memory = NULL; + } + + recorder_queue_redraw (recorder); +} + /* We use an event filter on the stage to get the XFixesCursorNotifyEvent * and also to track cursor position (when the cursor is over the stage's * input area); tracking cursor position here rather than with ClutterEvent @@ -567,23 +576,8 @@ recorder_event_filter (XEvent *xev, xev->xcookie.extension == recorder->xinput_opcode) input_event = (XIEvent *) xev->xcookie.data; - if (xev->xany.type == recorder->xfixes_event_base + XFixesCursorNotify) - { - XFixesCursorNotifyEvent *notify_event = (XFixesCursorNotifyEvent *)xev; - - if (notify_event->subtype == XFixesDisplayCursorNotify) - { - if (recorder->cursor_image) - { - cairo_surface_destroy (recorder->cursor_image); - recorder->cursor_image = NULL; - } - - recorder_queue_redraw (recorder); - } - } - else if (input_event != NULL && - input_event->evtype == XI_Motion) + if (input_event != NULL && + input_event->evtype == XI_Motion) { XIDeviceEvent *device_event = (XIDeviceEvent *) input_event; if (device_event->deviceid == VIRTUAL_CORE_POINTER_ID) @@ -807,14 +801,6 @@ recorder_set_stage (ShellRecorder *recorder, recorder_update_size (recorder); - recorder->have_xfixes = XFixesQueryExtension (clutter_x11_get_default_display (), - &recorder->xfixes_event_base, - &error_base); - if (recorder->have_xfixes) - XFixesSelectCursorInput (clutter_x11_get_default_display (), - clutter_x11_get_stage_window (stage), - XFixesDisplayCursorNotifyMask); - if (XQueryExtension (clutter_x11_get_default_display (), "XInputExtension", &recorder->xinput_opcode, @@ -843,6 +829,22 @@ recorder_set_stage (ShellRecorder *recorder, } } +static void +recorder_set_screen (ShellRecorder *recorder, + MetaScreen *screen) +{ + MetaCursorTracker *tracker; + + tracker = meta_cursor_tracker_get_for_screen (screen); + + if (tracker == recorder->cursor_tracker) + return; + + recorder->cursor_tracker = tracker; + g_signal_connect_object (tracker, "cursor-changed", + G_CALLBACK (on_cursor_changed), recorder, 0); +} + static void recorder_set_framerate (ShellRecorder *recorder, int framerate) @@ -918,6 +920,9 @@ shell_recorder_set_property (GObject *object, switch (prop_id) { + case PROP_SCREEN: + recorder_set_screen (recorder, g_value_get_object (value)); + break; case PROP_STAGE: recorder_set_stage (recorder, g_value_get_object (value)); break; @@ -979,6 +984,14 @@ shell_recorder_class_init (ShellRecorderClass *klass) gobject_class->get_property = shell_recorder_get_property; gobject_class->set_property = shell_recorder_set_property; + g_object_class_install_property (gobject_class, + PROP_SCREEN, + g_param_spec_object ("screen", + "Screen", + "Screen to record", + META_TYPE_SCREEN, + G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, PROP_STAGE, g_param_spec_object ("stage", diff --git a/src/test-recorder.c b/src/test-recorder.c deleted file mode 100644 index 86f937942..000000000 --- a/src/test-recorder.c +++ /dev/null @@ -1,127 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#define GST_USE_UNSTABLE_API -#include "shell-recorder.h" -#include -#include -#include - -/* Very simple test of the ShellRecorder class; shows some text strings - * moving around and records it. - */ -static ShellRecorder *recorder = NULL; - -static gboolean -stop_recording_timeout (ClutterActor *stage) -{ - if (recorder) - { - shell_recorder_close (recorder); - - /* quit when the recorder finishes closing - */ - g_object_weak_ref (G_OBJECT (recorder), - (GWeakNotify) - clutter_actor_destroy, - stage); - - g_object_unref (recorder); - } - else - { - clutter_actor_destroy (stage); - } - - return FALSE; -} - -static void -on_animation_completed (ClutterAnimation *animation, - ClutterStage *stage) -{ - g_timeout_add (1000, (GSourceFunc) stop_recording_timeout, stage); -} - -static void -on_stage_realized (ClutterActor *stage, - gpointer data) -{ - recorder = shell_recorder_new (CLUTTER_STAGE (stage)); - shell_recorder_set_file_template (recorder, "test-recorder.webm"); - shell_recorder_record (recorder, NULL); -} - -int main (int argc, char **argv) -{ - ClutterActor *stage; - ClutterActor *text; - ClutterAnimation *animation; - ClutterColor red, green, blue; - - gtk_init (&argc, &argv); - gst_init (&argc, &argv); - if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) - return 1; - - clutter_color_from_string (&red, "red"); - clutter_color_from_string (&green, "green"); - clutter_color_from_string (&blue, "blue"); - stage = clutter_stage_new (); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); - - text = g_object_new (CLUTTER_TYPE_TEXT, - "text", "Red", - "font-name", "Sans 40px", - "color", &red, - NULL); - clutter_actor_add_child (stage, text); - animation = clutter_actor_animate (text, - CLUTTER_EASE_IN_OUT_QUAD, - 3000, - "x", 320.0, - "y", 240.0, - NULL); - g_signal_connect (animation, "completed", - G_CALLBACK (on_animation_completed), stage); - - text = g_object_new (CLUTTER_TYPE_TEXT, - "text", "Blue", - "font-name", "Sans 40px", - "color", &blue, - "x", 640.0, - "y", 0.0, - NULL); - clutter_actor_set_anchor_point_from_gravity (text, CLUTTER_GRAVITY_NORTH_EAST); - clutter_actor_add_child (stage, text); - animation = clutter_actor_animate (text, - CLUTTER_EASE_IN_OUT_QUAD, - 3000, - "x", 320.0, - "y", 240.0, - NULL); - - text = g_object_new (CLUTTER_TYPE_TEXT, - "text", "Green", - "font-name", "Sans 40px", - "color", &green, - "x", 0.0, - "y", 480.0, - NULL); - clutter_actor_set_anchor_point_from_gravity (text, CLUTTER_GRAVITY_SOUTH_WEST); - clutter_actor_add_child (stage, text); - animation = clutter_actor_animate (text, - CLUTTER_EASE_IN_OUT_QUAD, - 3000, - "x", 320.0, - "y", 240.0, - NULL); - - g_signal_connect_after (stage, "realize", - G_CALLBACK (on_stage_realized), NULL); - - clutter_actor_show (stage); - - clutter_main (); - - return 0; -}